using System;
using System.Collections.Generic;
using System.Linq;
using WWB.SitePointPrivateMessages.Core.Infrastructure.Logging;
using WWB.SitePointPrivateMessages.Core.Model.DataImport;
using WWB.SitePointPrivateMessages.Core.Service;

namespace WWB.SitePointPrivateMessages.Core.Model.Messages
{
    public class MessageDatabase
    {
        private readonly IMessageSearcher searcher;
        public IEnumerable<Folder> Folders { get; private set; }
        public IEnumerable<ForumUser> Users { get; private set; }

        public IEnumerable<PrivateMessage> Messages
        {
            get
            {
                return Folders.SelectMany(x => x.Messages);
            }
        }

        public MessageDatabase(IMessageSearcher searcher, IEnumerable<Folder> folders, IEnumerable<ForumUser> users)
        {
            if (searcher == null) throw new ArgumentNullException("searcher");
            this.searcher = searcher;
            if (folders == null) throw new ArgumentNullException("folders");
            if (users == null) throw new ArgumentNullException("users");
            Folders = folders;
            Users = users;
            this.searcher.IndexMessages(Messages);
        }

        /// <summary>
        /// Exports a message database to a SitePointMessageExport
        /// </summary>
        /// <param name="outputLog">Output log vector</param>
        /// <returns>Export-style copy of the database</returns>
        public SitePointMessageExport ExportMessages(ILogger outputLog)
        {
            if (outputLog == null) throw new ArgumentNullException("outputLog");
            outputLog.LogMessage("Starting message export transformation at {0}.", DateTime.Now);
            outputLog.LogMessage("{0} folders to import.", Folders.Count());
            var fex = new List<ExportedFolder>(Folders.Count());
            fex.AddRange(Folders.Select(f => f.ConvertToExport(outputLog)));
            var smex = new SitePointMessageExport
                           {
                               Folders = fex.ToArray()
                           };
            return smex;
        }

        public IEnumerable<PrivateMessage> SearchMessages(string searchTerm, string[] selectedFolders, int[] selectedUsers, DateTime startDate, DateTime endDate)
        {
            IEnumerable<PrivateMessage> startingMessages = null;
            if (string.IsNullOrWhiteSpace(searchTerm))
            {
                startingMessages = Messages;
            }
            else
            {
                startingMessages = searcher.SearchMessages(searchTerm);
            }
            var ret = startingMessages.Where(x => x.DateStamp >= startDate && x.DateStamp <= endDate);
            if (selectedFolders != null && selectedFolders.Count() > 0)
            {
                ret = ret.Where(x => selectedFolders.Contains(x.Folder.Name));
            }
            if (selectedUsers != null && selectedUsers.Count() > 0)
            {
                ret = ret.Where(x => x.IsRelatedToUsers(selectedUsers));
            }
            return ret;
        }


        public IEnumerable<PrivateMessage> SearchMessages(string searchTerm, string[] selectedFolders, int[] selectedUsers)
        {
            return SearchMessages(searchTerm, selectedFolders, selectedUsers, DateTime.MinValue, DateTime.MaxValue);
        }
    }
}